package manager;

import entity.ExcelEntity;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableBooleanValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import util.ExcelReader;
import util.ExcelWriter;
import util.JavaFxScheduler;

import java.io.File;
import java.util.List;

public class ExcelManager {
    private ObservableList<String> importedFilePathList;
    private SimpleStringProperty exportPath;
    private SimpleBooleanProperty isComplete;
    private SimpleBooleanProperty isActioning;

    private static final String EXPORT_FILE_NAME = "result.xlsx";


    public ExcelManager () {
        importedFilePathList = FXCollections.observableArrayList();
        exportPath = new SimpleStringProperty();
        isComplete = new SimpleBooleanProperty(false);
        isActioning = new SimpleBooleanProperty(false);
    }

    public boolean action(Mode actionType) {
        isActioning.setValue(true);
        switch (actionType) {
            case toExcel:
                try {
                    importAndExportToExcel();
                    return true;
                } catch (Exception e) {
                    return false;
                }
            default:
        }

        return false;
    }

    private void importAndExportToExcel() {
        Observable.fromIterable(importedFilePathList)
                .observeOn(Schedulers.io())
                .map(this::readExcel)
                .observeOn(Schedulers.io())
                .toList()
                .map(excelEntities -> {
                    writeToExcel(excelEntities);
                    return 1;
                })
                .observeOn(JavaFxScheduler.platform())
                .doOnSuccess(integer -> notifySuccess())
                .doOnError(this::notifyFailed)
                .subscribe();
    }

    private void notifyFailed(Throwable throwable) {
        isComplete.setValue(false);
        isActioning.setValue(false);
    }

    private void notifySuccess() {
        isComplete.setValue(true);
        isActioning.setValue(false);
    }

    private void writeToExcel(List<ExcelEntity> excelEntitys) {
        System.out.println(excelEntitys);
        ExcelWriter.exportData(excelEntitys, getExportPath() + File.separator + EXPORT_FILE_NAME);
    }

    private ExcelEntity readExcel(String fileName) {
        return ExcelReader.readExcel(fileName);
    }

    public ObservableList<String> getImportedFilePathList() {
        return importedFilePathList;
    }

    public void setImportedFilePathList(ObservableList<String> importedFilePathList) {
        this.importedFilePathList = importedFilePathList;
    }

    public String getExportPath() {
        return exportPath.get();
    }

    public SimpleStringProperty exportPathProperty() {
        return exportPath;
    }

    public void setExportPath(String exportPath) {
        this.exportPath.set(exportPath);
    }

    public Boolean getIsComplete() {
        return isComplete.get();
    }

    public ObservableBooleanValue isCompleteProperty() {
        return isComplete;
    }

    public void addImportItem(String fileName) {
        this.importedFilePathList.add(fileName);
    }

    public boolean isImportFileListNullOrEmpty() {
        return this.importedFilePathList ==null || this.importedFilePathList.isEmpty();
    }

    public boolean isExportFileNullOrEmpty() {
        return this.exportPath.getValueSafe().isEmpty();
    }

    public void clearImportFileList() {
        this.importedFilePathList.clear();
    }

    public void removeImportFile(String item) {
        this.importedFilePathList.remove(item);
    }

    public boolean isIsActioning() {
        return isActioning.get();
    }

    public SimpleBooleanProperty isActioningProperty() {
        return isActioning;
    }

    public void setIsActioning(boolean isActioning) {
        this.isActioning.set(isActioning);
    }

    public boolean isIsComplete() {
        return isComplete.get();
    }

    public void setIsComplete(boolean isComplete) {
        this.isComplete.set(isComplete);
    }

    public enum Mode { toExcel }
}
